import os
from PIL import Image

def preprocess_image(img, target_width=300, target_height=400):
    """
    预处理图片：裁剪和缩放
    
    参数:
    img: PIL图片对象
    target_width: 目标宽度
    target_height: 目标高度
    
    返回:
    处理后的PIL图片对象
    """
    # 获取原始尺寸
    original_width, original_height = img.size
    original_ratio = original_width / original_height
    target_ratio = target_width / target_height
    
    print(f"原始尺寸: {original_width}x{original_height}, 原始宽高比: {original_ratio:.2f}")
    print(f"目标尺寸: {target_width}x{target_height}, 目标宽高比: {target_ratio:.2f}")
    
    # 如果宽高比相同，直接缩放
    if abs(original_ratio - target_ratio) < 0.01:
        print("宽高比相同，直接缩放")
        return img.resize((target_width, target_height), Image.Resampling.LANCZOS)
    
    # 计算裁剪区域
    if original_ratio > target_ratio:
        # 原图较宽，需要裁剪左右
        new_width = int(original_height * target_ratio)
        left = (original_width - new_width) // 2
        top = 0
        right = left + new_width
        bottom = original_height
        print(f"原图较宽，裁剪左右: {left}px 和 {original_width - right}px")
    else:
        # 原图较高，需要裁剪上下
        new_height = int(original_width / target_ratio)
        left = 0
        top = (original_height - new_height) // 2
        right = original_width
        bottom = top + new_height
        print(f"原图较高，裁剪上下: {top}px 和 {original_height - bottom}px")
    
    # 执行裁剪
    cropped_img = img.crop((left, top, right, bottom))
    
    # 缩放到目标尺寸
    resized_img = cropped_img.resize((target_width, target_height), Image.Resampling.LANCZOS)
    
    return resized_img

def compress_image(input_path, output_path=None, quality=85, target_size=100, preprocess=False):
    """
    压缩JPG图片到指定大小以内
    
    参数:
    input_path: 输入图片路径
    output_path: 输出图片路径(可选)
    quality: 初始压缩质量(1-100)
    target_size: 目标大小(KB)
    preprocess: 是否进行预处理(裁剪和缩放)
    """
    
    # 如果没有指定输出路径，在原文件名后添加_compressed
    if output_path is None:
        name, ext = os.path.splitext(input_path)
        output_path = f"{name}_compressed{ext}"
    
    # 打开原始图片
    try:
        with Image.open(input_path) as img:
            # 确保是RGB模式(避免RGBA等问题)
            if img.mode in ('RGBA', 'P', 'LA'):
                img = img.convert('RGB')
            
            # 如果启用预处理，先进行裁剪和缩放
            if preprocess:
                print("正在进行图片预处理...")
                img = preprocess_image(img, 300, 400)
                print("预处理完成")
            
            # 获取原始文件大小
            original_size = os.path.getsize(input_path) / 1024  # 转换为KB
            
            print(f"原始图片大小: {original_size:.2f} KB")
            
            # 如果已经小于目标大小，直接复制
            if original_size <= target_size:
                img.save(output_path, 'JPEG', quality=quality)
                print(f"图片已小于{target_size}KB，无需压缩")
                return True
            
            # 逐步降低质量直到达到目标大小
            current_quality = quality
            min_quality = 10  # 最低质量限制，避免图片质量过差
            
            while current_quality >= min_quality:
                # 保存到内存先检查大小
                from io import BytesIO
                buffer = BytesIO()
                img.save(buffer, 'JPEG', quality=current_quality, optimize=True)
                buffer_size = len(buffer.getvalue()) / 1024  # KB
                
                print(f"尝试质量 {current_quality}%, 大小: {buffer_size:.2f} KB")
                
                if buffer_size <= target_size:
                    # 达到目标大小，保存文件
                    with open(output_path, 'wb') as f:
                        f.write(buffer.getvalue())
                    print(f"压缩成功! 最终质量: {current_quality}%, 大小: {buffer_size:.2f} KB")
                    return True
                
                # 质量调整步长根据当前大小动态调整
                if buffer_size > target_size * 2:
                    current_quality -= 15
                elif buffer_size > target_size * 1.5:
                    current_quality -= 10
                else:
                    current_quality -= 5
            
            # 如果质量降到最低仍然太大，使用最低质量保存
            img.save(output_path, 'JPEG', quality=min_quality, optimize=True)
            final_size = os.path.getsize(output_path) / 1024
            print(f"警告: 使用最低质量({min_quality}%)压缩，最终大小: {final_size:.2f} KB")
            return final_size <= target_size
            
    except Exception as e:
        print(f"处理图片时出错: {e}")
        return False

if __name__ == "__main__":
    # 直接在这里指定参数
    input_path = "/home/ubuntu/图片/帅华飞的照片.jpg"  # 替换为你的输入图片路径
    output_path = "/home/ubuntu/图片/帅华飞的照片_100.jpg"  # 输出路径，None表示自动生成
    quality = 100  # 初始压缩质量
    preprocess = True  # 是否进行预处理(裁剪和缩放)
    
    # 检查输入文件是否存在
    if not os.path.exists(input_path):
        print(f"错误: 文件 '{input_path}' 不存在")
        exit()
    
    # 检查文件格式
    if not input_path.lower().endswith(('.jpg', '.jpeg')):
        print("警告: 建议使用JPG格式图片")
    
    # 执行压缩
    success = compress_image(
        input_path=input_path,
        output_path=output_path,
        quality=quality,
        target_size=100,
        preprocess=preprocess
    )
    
    if success:
        print("图片压缩完成!")
    else:
        print("图片压缩失败!")